//==============================================================================
#include "GameServer.h"

string GameServer::DEFAULT_PORT = "8080";
//==============================================================================
GameServer::GameServer(string sceneName)
{
	setPort(DEFAULT_PORT);
	setIsReady(false);
	_allPlayersReady = false;

	setPlayerSessionCount(0);
	
	setModel(new Model(this, sceneName));
	setReceiver(new ServerReceiver(this));

	setSocket(new ServerSocket(getPort()));
	getSocket()->setOption(TCP, NO_DELAY);
}
//------------------------------------------------------------------------------
GameServer::GameServer(string sceneName, string port)
{
	setPort(port);
	setIsReady(false);
	_allPlayersReady = false;

	setPlayerSessionCount(0);

	setModel(new Model(this, sceneName));
	setReceiver(new ServerReceiver(this));

	setSocket(new ServerSocket(getPort()));
	getSocket()->setOption(TCP, NO_DELAY);
}
//------------------------------------------------------------------------------
GameServer::~GameServer()
{
	delete getSocket();
	delete getReceiver();
	delete getModel();
	delete this->modelThread;
	delete this->receiverThread;
}
//------------------------------------------------------------------------------
bool GameServer::allPlayersReady()
{
	return this->_allPlayersReady;
}
//------------------------------------------------------------------------------
void GameServer::setPlayerSessionCount(int numb)
{
	this->playerSessionCount = numb;
}
//------------------------------------------------------------------------------
int GameServer::getPlayerSessionCount(void)
{
	return this->playerSessionCount;
}
//------------------------------------------------------------------------------
CriticalSection* GameServer::getPlayerSessionCountLock(void)
{
	return &this->playerSessionCountLock;
}
//------------------------------------------------------------------------------
void GameServer::setPort(string port)
{
	this->port = port;
}
//------------------------------------------------------------------------------
string GameServer::getPort(void)
{
	return this->port;
}
//------------------------------------------------------------------------------
list<SessionHandler*>* GameServer::getSessionsLst(void)
{
	return &this->sessionsLst;
}
//------------------------------------------------------------------------------
list<Thread*>* GameServer::getThreadsLst(void)
{
	return &this->threadsLst;
}
//------------------------------------------------------------------------------
CriticalSection* GameServer::getSessionsLstLock(void)
{
	return &this->sessionsLstLock;
}
//------------------------------------------------------------------------------
CriticalSection* GameServer::getNewGameEventsLock(void)
{
	return &this->newGameEventsLock;
}
//------------------------------------------------------------------------------
queue<GameEvent*>* GameServer::getNewGameEvents(void)
{
	return &this->newGameEvents;
}
//------------------------------------------------------------------------------
void GameServer::setSocket(ServerSocket* socket)
{
	this->socket = socket;
}
//------------------------------------------------------------------------------
ServerSocket* GameServer::getSocket(void)
{
	return this->socket;
}
//------------------------------------------------------------------------------
void GameServer::setModel(Model* model)
{
	this->model = model;
}
//------------------------------------------------------------------------------
Model* GameServer::getModel(void)
{
	return this->model;
}
//------------------------------------------------------------------------------
void GameServer::setReceiver(ServerReceiver* receiver)
{
	this->receiver = receiver;
}
//------------------------------------------------------------------------------
ServerReceiver* GameServer::getReceiver()
{
	return this->receiver;
}
//------------------------------------------------------------------------------
void GameServer::setIsReady(bool flag)
{
	this->_isReady = flag;
}
//------------------------------------------------------------------------------
bool GameServer::isReady(void)
{
	return _isReady;
}
//------------------------------------------------------------------------------
bool GameServer::addNewPlayerSession()
{
	bool operationResult = false;
	getPlayerSessionCountLock()->adquire();
	if(getPlayerSessionCount() < SERVER_MAX_PLAYER_SESSIONS)
	{
		this->playerSessionCount++;
		operationResult = true;
	}
	getPlayerSessionCountLock()->release();
	return operationResult;
}
//------------------------------------------------------------------------------
bool GameServer::deletePlayerSession()
{
	bool operationResult = false;
	getPlayerSessionCountLock()->adquire();
	this->playerSessionCount--;
	operationResult = true;
	getPlayerSessionCountLock()->release();
	return operationResult;
}
//------------------------------------------------------------------------------
bool GameServer::addNewObserverSession()
{
	return true;
}
//------------------------------------------------------------------------------
DWORD GameServer::run(void)
{
	return start();
}
//------------------------------------------------------------------------------
int GameServer::start(void)
{
	Log::getInstance()->info("[SERVER] Starting GameServer...");
	Log::getInstance()->info("[SERVER] Server ConnectionSocket : " + getSocket()->toString());
	this->modelThread = ThreadPool::getInstance()->execute(getModel());
	while(!getModel()->isReady())
		Sleep(0);
	this->receiverThread = ThreadPool::getInstance()->execute(getReceiver());
	setIsReady(true);
	Log::getInstance()->info("[SERVER] Waiting for Players...");
	while(!getPlayerSessionCount() >= SERVER_MAX_PLAYER_SESSIONS)
		Sleep(100);
	_allPlayersReady = false;
	while(!_allPlayersReady)
	{
		list <SessionHandler*>::iterator it2 = getSessionsLst()->begin();
		int playersReady = 0;
		while(it2 != getSessionsLst()->end())
		{
			if((*it2)->isReady())
			{
				playersReady++;
			}
			it2++;
		}
		if (playersReady >= SERVER_MAX_PLAYER_SESSIONS)
			_allPlayersReady = true;
		else
			Sleep(100);
	}

	return 0;
}
//------------------------------------------------------------------------------
void GameServer::shutdown(void)
{
	getReceiver()->stopReceiving();
	getSocket()->doClose();
	this->receiverThread->join(INFINITE);
	getModel()->stopProcessingUpdates();
	this->modelThread->join(INFINITE);
	//getSocket()->doShutdown();
	
	SessionHandler* session;
	while (!getSessionsLst()->empty())
	{
		session = getSessionsLst()->front();
		getSessionsLst()->pop_front();
		session->stopHandlingSession();
		session->getClientSocket()->doShutdown();
		session->getClientSocket()->doClose();
		Thread* thread = getThreadsLst()->front();
		getThreadsLst()->pop_front();
		thread->join(INFINITE);
		delete thread;
		delete session;
	}
	setIsReady(false);
}
//------------------------------------------------------------------------------
void GameServer::addNewGameEvent(GameEvent* gameEvent)
{
	getNewGameEventsLock()->adquire();
	getNewGameEvents()->push(gameEvent);
	getNewGameEventsLock()->release();
}
